from __future__ import annotations

import json, logging
from contextlib import asynccontextmanager
from pathlib import Path
from typing import List, Dict, Any

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

from assistant import ProductRecommendationAssistant, Product, User
from assistant.llm_agent import generate_reason  # ⭐ 大模型理由

# ------------------------------------------------------------------------
logger = logging.getLogger("rec-service")
logger.setLevel(logging.INFO)
if not logger.handlers:
    h = logging.StreamHandler()
    h.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    logger.addHandler(h)

DATA_DIR = Path(__file__).parent / "data"
rec = ProductRecommendationAssistant()

def _load_initial_data() -> None:
    users_raw = json.loads((DATA_DIR / "users.json").read_text(encoding="utf-8"))
    goods_raw = json.loads((DATA_DIR / "goods.json").read_text(encoding="utf-8"))
    rec.load_data([User(**u) for u in users_raw], [Product(**p) for p in goods_raw])
    logger.info("Loaded %d users, %d products", len(users_raw), len(goods_raw))

@asynccontextmanager
async def lifespan(app: FastAPI):
    _load_initial_data()
    yield

app = FastAPI(
    title="Product Recommendation API",
    version="1.1.0",
    lifespan=lifespan
)

# ------------------------------------------------------------------------
class PurchaseIn(BaseModel):
    product_id: int

class ProductIn(BaseModel):
    id: int
    name: str
    category: str
    price: float
    tags: list[str] = []

# ✅ ✅ ✅ 只保留这个 /api/recommend 接口（修复重复声明）
@app.get("/api/recommend", response_model=List[Dict[str, Any]])
async def recommend(username: str):
    items = rec.recommend_products(username)
    user_summary = rec.describe_user(username)

    results = []
    for item in items:
        reason = generate_reason(user_summary, item)
        enriched = dict(item)
        enriched["reason"] = reason
        results.append(enriched)
    return results

# ------------------------------------------------------------------------
@app.get("/api/product/{name}")
async def product(name: str):
    p = rec.get_product_details(name)
    if p:
        return p
    raise HTTPException(status_code=404, detail="Product not found")

@app.post("/api/users/{username}/purchase")
async def add_purchase(username: str, payload: PurchaseIn):
    try:
        rec.add_purchase(username, payload.product_id)
        users_path = DATA_DIR / "users.json"
        users_serializable = [
            u.model_dump() if hasattr(u, "model_dump") else u.dict()
            for u in rec._users.values()
        ]
        users_path.write_text(json.dumps(users_serializable, indent=2), encoding="utf-8")
        return {"msg": "recorded"}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

@app.post("/api/products")
async def add_product(payload: ProductIn):
    rec.add_product(Product(**payload.dict()))
    return {"msg": "product added"}

@app.get("/api/users/{username}")
def get_user(username: str):
    u = rec.get_user_data(username)
    if u is None:
        raise HTTPException(status_code=404, detail="User not found")
    items = [
        rec.get_product_by_id(pid).model_dump()
        for pid in u.purchased_product_ids
        if rec.get_product_by_id(pid)
    ]
    return {"username": username, "purchased_items": items}
